/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jogopoo.Grafico;

import Engine.Fisica.Clip;
import java.util.logging.Level;
import java.util.logging.Logger;
import Engine.Fisica.Planeta;
import Itens.Raio;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.ArrayList;
import javax.swing.JPanel;
import jogopoo.Efeitos.Efeito;
import jogopoo.Efeitos.EfeitosTela;
import Itens.Explosao;
import Itens.NuclearEx;
import jogopoo.Interface.Janela;
import jogopoo.Personagem.PersInimigos;
import jogopoo.Personagem.PersNave;
import jogopoo.Util.Timer;
import jogopoo.Util.TimerListener;
import jogopoo.Personagem.TipoPersonagens;
import jogopoo.Personagem.TipoPersonagens.TPersonagem;
import jogopoo.Util.Arquivo;

/*
 *
 * @author acer_5542
 * 
 */
/**
 * Classe responsavel pela fase do jogo, classe implementa TimerListener para
 * para tratamento de tempo (delay),contem vetores de inimigos, nave do tipo
 * PersNave que eh o player e atributos que vao ordenar o movimento dos inimigos
 *
 */
public class GrafCenario extends JPanel implements TimerListener {

    public GrafCenario(Janela janela, String Nome, int id) throws InterruptedException {
        this.janela = janela;
        this.id = id;
        this.setBackground(Color.BLACK);
        this.timer = new Timer(this, 50, this);
        this.treme = false;
        this.tremeStrong = 10;
        this.fim = false;
        this.msg = false;
        EfeitosTela.setAlpha(0);
        nave = new PersNave[1];
        /// pega do arquivo
        String buffer = new String();
        try {
            buffer = Arquivo.carregar("cenarios/" + Nome + ".cnr");
        } catch (Exception e) {
            e.printStackTrace();
        }
        /// tira do buffer a sequencia da ordem dos alliens

        int i = 0;
        int j = 0;
        while (buffer.charAt(i) != '#') {
            ++i;
        }
        char nAliens[] = new char[i];/// numero de aliens a ser criado
        buffer.getChars(j, nAliens.length, nAliens, 0);
        ++i;
        j = i;
        while (buffer.charAt(i) != '#') {
            ++i;
        }
        char nAliensPF[] = new char[i - j];// numero de aliens por fileira
        buffer.getChars(j, j + nAliensPF.length, nAliensPF, 0);
        ++i;
        j = i;
        while (buffer.charAt(i) != '#') {
            ++i;
        }
        backNumero = new char[i - j];// numero do background
        buffer.getChars(j, j + backNumero.length, backNumero, 0);
        ++i;
        j = i;
        while (buffer.charAt(i) != '#') {
            ++i;
        }
        char nPlanetas[] = new char[i - j];// numero do background
        buffer.getChars(j, j + nPlanetas.length, nPlanetas, 0);


        nA = Integer.parseInt(String.copyValueOf(nAliens));
        nP = Integer.parseInt(String.copyValueOf(nPlanetas));
        nAPF = Integer.parseInt(String.copyValueOf(nAliensPF));
        ordemAliens = new char[nA];
        buffer.getChars(i + 1, nA + i + 1, ordemAliens, 0);

        for (j = 0; j < nA; ++j) {
            if (ordemAliens[j] == 'a') {
                lista_inimigos.add((PersInimigos) TipoPersonagens.getInstance(this, TPersonagem.ALIEN_AZUL));
            } else if (ordemAliens[j] == 'v') {
                lista_inimigos.add((PersInimigos) TipoPersonagens.getInstance(this, TPersonagem.ALIEN_VERDE));
            } else if (ordemAliens[j] == 'r') {
                lista_inimigos.add((PersInimigos) TipoPersonagens.getInstance(this, TPersonagem.ALIEN_ROSA));
            } else if (ordemAliens[j] == 'l') {
                lista_inimigos.add((PersInimigos) TipoPersonagens.getInstance(this, TPersonagem.ALIEN_LARANJA));
            }
            lista_inimigos.get(j).getPosicao().x += 20 + (j % nAPF) * 60;
            lista_inimigos.get(j).getPosicao().y += 50 * (j / nAPF);
            lista_inimigos.get(j).setId(j);
        }

        nave[0] = (PersNave) TipoPersonagens.getInstance(this, TPersonagem.NAVE);
        nave[0].getPosicao().x += 480;
        nave[0].getPosicao().y += 571;

        i = i + nA + 2;
        int k = i;
        ////essa parte do codigo carrega os planetas do buffer que foi pego do arquivo
        for (j = 0; j < nP; ++j) {

            while (buffer.charAt(i) != ',') {
                ++i;
            }
            char plntX[] = new char[i - k];/// numero de aliens a ser criado
            buffer.getChars(k, k + plntX.length, plntX, 0);
            ++i;
            k = i;

            while (buffer.charAt(i) != ',') {
                ++i;
            }
            char plntY[] = new char[i - k];/// numero de aliens a ser criado
            buffer.getChars(k, k + plntY.length, plntY, 0);
            ++i;
            k = i;
            while (buffer.charAt(i) != ',') {
                ++i;
            }
            char plntMassa[] = new char[i - k];/// numero de aliens a ser criado
            buffer.getChars(k, k + plntMassa.length, plntMassa, 0);
            ++i;
            k = i;

            char plntSize[] = new char[1];
            plntSize[0] = buffer.charAt(i);
            i += 2;
            char plntColor = buffer.charAt(i);
            i += 2;
            k = i;

            lista_planeta.add(new Planeta(this, Integer.parseInt(String.copyValueOf(plntX)),
                    Integer.parseInt(String.copyValueOf(plntY)),
                    Integer.parseInt(String.copyValueOf(plntMassa)),
                    Integer.parseInt(String.copyValueOf(plntSize)), plntColor));

        }
        Explosao.carregarImagens(this);
        NuclearEx.carregarImagens(this);
        Raio.carregarImagens(this);
        clip = new Clip(this);
        Clip.carregarImagens(this);
        efeitosTela = new EfeitosTela();
        barraInfo = new BarraInfo(this);
        BarraInfo.carregarImagens(this);
        this.timer.start();
    }

    /**
     * metodo sobescrito da classe JPanel, adiciona todos os objetos na cena
     * colocando os respectivos metos de desenhar de cada objeto dentro desta
     * @param cena
     */
    @Override
    protected void paintComponent(Graphics cena) {
        super.paintComponent(cena);

        Graphics2D cena2 = (Graphics2D) cena;
        clip.desenhaBackground(cena2);
        for (int i = 0; i < lista_planeta.size(); ++i) {
            lista_planeta.get(i).desenha(cena2);
        }
        clip.desenha(cena2, lista_planeta);

        for (int i = 0; i < lista_inimigos.size(); ++i) {
            lista_inimigos.get(i).desenha(cena2);
        }

        nave[0].desenha(cena2);
        for (int i = 0; i < nave[0].getListaLaser().size(); ++i) {
            nave[0].getListaLaser().get(i).desenha(cena2);
        }

        for (int i = 0; i < lista_efeitos.size(); ++i) {
            lista_efeitos.get(i).desenha(cena2);
        }

        for (int i = 0; i < lista_raios.size(); ++i) {
            lista_raios.get(i).desenha(cena2);
        }
        barraInfo.desenha(cena2);
        EfeitosTela.branquearTela(cena2);
    }

    /**
     * metodo responsavel por atualizar a situacao de cada objeto na fase,
     * eh ultilizada na classe Timer,contem aqui a logica do movimento dos inimigos
     * usando os atributos da classe: inmgs_direcao, inmgs_deslocamento, inmgs_y.
     */
    public void update() {
        ///atualizar atributos do Player
        nave[0].recebeComandosTeclado();
        nave[0].move();
        ////atualizar atributos dos Tiros
        for (int i = 0; i < nave[0].getListaLaser().size(); ++i) {
            nave[0].getListaLaser().get(i).move();
            nave[0].getListaLaser().get(i).atualiza();
        }
        ////atualizar atributos dos Inimigos
        for (int i = 0; i < lista_inimigos.size(); i++) {
            lista_inimigos.get(i).mover(this.inmgs_direcao * (2), this.inmgs_y);
            if ((int) (Math.random() * 100) == 1) {
                lista_inimigos.get(i).atira();
                if(lista_inimigos.get(i).getPosicao().y > 530){
                    this.janela.gameOver(this);
                }
            }
        }
        ////atualiza atributos dos raios
        for (int i = 0; i < lista_raios.size(); i++) {
            lista_raios.get(i).move();
        }
        ////atualiza atributos dos efeitos
        for (int i = 0; i < lista_efeitos.size(); i++) {
            lista_efeitos.get(i).especial();
        }


        this.inmgs_y = 0;
        if (this.inmgs_deslocamento >= (960 - (66 * (nAPF))) || this.inmgs_deslocamento <= -(960 - (66 * (nAPF)))) {
            this.inmgs_deslocamento = 0;
            this.inmgs_direcao *= -1;
            this.inmgs_y += 16;
        } else {
            this.inmgs_deslocamento += this.inmgs_direcao * 2;
        }
        if(this.msg == true){
            ++mensagemDelay;
        }
        if(mensagemDelay > 50){
            this.msg = false;
            mensagemDelay= 0;
        }
        efeitosTela.tremer(this, 10);
        this.repaint();
        if (lista_inimigos.isEmpty() == true && fim == false) {
            if((janela.getListaNomeCenarios().size() != this.id + 1)){
            try {
                GrafCenario cenario2 = new GrafCenario(janela, janela.getListaNomeCenarios().get(this.id + 1), this.id + 1);
                janela.mudaFase(this, cenario2);
            } catch (InterruptedException ex) {
                Logger.getLogger(GrafCenario.class.getName()).log(Level.SEVERE, null, ex);
            }
            }else{
                janela.gameOver(this);
            }
            fim = true;
        }

    }

    /**
     * Retorna o objeto jogador.
     * @return
     */
    public PersNave getPlayer() {
        return this.nave[0];
    }
/**
 * retorna o Numero de Aliens por Filheira, da fase
 * @return nAPF
 */
    public int getNAPF() {
        return this.nAPF;
    }
/**
 * retorna o Numero de Aliens da fase
 * @return
 */
    public int getNA() {
        return this.nA;
    }
/**
 * retorna a lista de Planetas
 * @return lista_planeta
 */
    public ArrayList<Planeta> getListaPlaneta() {
        return lista_planeta;
    }
/**
 * retorna a lista de Planetas
 * @return lista_efeitos
 */
    public ArrayList<Efeito> getListaEfeitos() {
        return lista_efeitos;
    }
/**
 * retorna a lista de inimigos
 * @return lista_inimigos
 */
    public ArrayList<PersInimigos> getListaAliens() {
        return lista_inimigos;
    }
/**
 * retorna a lista de raios "tiro dos inimigos"
 * @return lista_raios
 */
    public ArrayList<Raio> getListaRaios() {
        return lista_raios;
    }
/**
 * retorna o char correspondente ao allien que correspondem ao id do vetor de aliens
 * @param id
 * @return ordemAliens[id]
 */
    public char getAlienChar(int id) {
        return ordemAliens[id];
    }
/**
 * retorna o numero do background em string
 * retorna String
 * @return backNumero
 */
    public String getBackgroundNumero() {
        return String.copyValueOf(backNumero);
    }
/**
 *Seta o char do alien que corresponde ao id no vetor de aliens
 * @param id
 * @param
 * @return ordemAliens[id]
 */
    public char setAlienChar(int id, char ch) {
        return ordemAliens[id] = ch;
    }
/**
 * retorna a variavel booleana Treme que serve como flag para tremer a tela
 * @return
 */
    public boolean getTreme() {
        return this.treme;
    }
/**
 * retorna o objeto Timer
 * @return timer
 */
    public Timer getTimer() {
        return this.timer;
    }
/**
 * retorna o objeto janela onde o cenario esta sendo rodado
 * @return janela
 */
    public Janela getJanela() {
        return janela;
    }
/**
 * retorna a flag Fim que determina o fim do cenario
 * @return fim
 */
    public boolean getFim() {
        return fim;
    }
/**
 * Seta a variavel FIm que determina o fim do cenario
 * @param fim
 */
    public void setFim(boolean fim) {
        this.fim = fim;
    }



/**
 * Retorna o objeto Barra de informacoes do cenario
 * @return
 */
    public BarraInfo getBarraInfo() {
        return this.barraInfo;
    }
/**
 * Seta a flag Treme que serve para tremer a tela
 * @param treme
 */
    public void setTreme(boolean treme) {
        this.treme = treme;
    }
/**
 * Seta a variavel tremeStrong que e a amplitude da tremida da tela
 * @param tremeStrong
 */
    public void setTremeStrong(int tremeStrong){
        this.tremeStrong = tremeStrong;
    }
/**
 * retorna a variavel tremeStrong que é a amplitude da tremida da tela
 * @return tremeStrong
 */
    public int getTremeStrong(){
        return tremeStrong;
    }
/**
 * retora a variabel Msg que é a flag que determina se a Mensagem da tela esta
 * sendo mostrada
 * @return
 */
    public boolean getMsg(){
        return msg;
    }
/**
 * Seta a flag setMsg que determina se a Mensagem da tela esta
 * @param msg
 */
    public void setMsg(boolean msg){
        this.msg = msg;
    }
/**
 * Retorna a mensagem que e exibida na tela
 * @return mensagem
 */
    public String getMensagem(){
        return mensagem;
    }
/**
 * Seta a mensagem que sera exibida na tela
 * @param mensagem
 */
    public void setMensagem(String mensagem){
        this.mensagem = mensagem;
    }
    private Janela janela;
    private Timer timer;
    private int id;
    private PersNave[] nave;
    private int inmgs_deslocamento = 0;
    private int inmgs_direcao = 1;
    private int inmgs_y = 0;
    private EfeitosTela efeitosTela;
    private ArrayList<Planeta> lista_planeta = new ArrayList<Planeta>();
    private ArrayList<Efeito> lista_efeitos = new ArrayList<Efeito>();
    private ArrayList<PersInimigos> lista_inimigos = new ArrayList<PersInimigos>();
    private ArrayList<Raio> lista_raios = new ArrayList<Raio>();
    private char ordemAliens[];
    private static char backNumero[];
    private int nA;    //numero de aliens
    private int nP;    //numero de planetas
    private int nAPF;  //numero de aliens por linha, fileira
    private Clip clip;
    private boolean treme;
    private int tremeStrong;
    private boolean fim;
    private BarraInfo barraInfo;
    private boolean msg;
    private String mensagem;
    private int mensagemDelay;
}

